#include "messageshowarea.h"

#include "debug.h"
#include "userinfowidget.h"

///////////////////////////////
/// 消息展示区
///////////////////////////////

MessageShowArea::MessageShowArea()
{
    // 设置必要的属性
    this->setFixedHeight(400);
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    this->setWidgetResizable(true);
    // 设置滚动条样式
    this->horizontalScrollBar()->setStyleSheet("QScrollBar:horizontal { height:0px; }");
    this->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width:1px; "
                                             "background-color:rgb(25, 25, 25); }");
    container = new QWidget();
    this->setWidget(container);
    // 添加布局管理器
    QVBoxLayout* layout = new QVBoxLayout();
    layout->setSpacing(0);
    layout->setContentsMargins(10, 0, 10, 5);
    layout->setAlignment(Qt::AlignTop);
    container->setLayout(layout);

#if TEST_F
    for(int i = 0;i < 20;i ++) {
        model::UserInfo userInfo;
        userInfo.avatar = QIcon(":/resource/image/default_avatar.png");
        userInfo.nickname = "lufei" + QString::number(i);
        userInfo.userId = QString::number(i);
        userInfo.description =  "成为海贼王的男人";
        userInfo.phone = "15962491816";
        Message msg = Message::makeMessage(model::TEXT_TYPE, "", userInfo, ("这是一条消息" + QString::number(i)).toUtf8(), "");
        this->addMsgItem(true, msg);
    }

    model::UserInfo userInfo;
    userInfo.avatar = QIcon(":/resource/image/default_avatar.png");
    userInfo.nickname = "zoro";
    userInfo.userId = "30";
    userInfo.description =  "成为海贼王的男人";
    userInfo.phone = "15962491816";
    QString content = "这是一条消息这是一条消息这是一条消息这是一条消息这是一条消息这是一条消息这是一条消息这是一条消息这是一条消息这是一条消息";
    Message msg = Message::makeMessage(model::TEXT_TYPE, "", userInfo, content.toUtf8(), "");
    this->addMsgItem(false, msg);

#endif

}

void MessageShowArea::addMsgItem(bool isLeft, const Message& msg)
{
    MessageItem* msgItem = MessageItem::makeMesageItem(isLeft, msg);
    container->layout()->addWidget(msgItem);
}

void MessageShowArea::addFrontMsgItem(bool isLeft, const Message& msg)
{
    MessageItem* msgItem = MessageItem::makeMesageItem(isLeft, msg);
    QVBoxLayout* layout = dynamic_cast<QVBoxLayout*>(container->layout());
    layout->insertWidget(0, msgItem);
}

void MessageShowArea::clear()
{
    for(int i = container->layout()->count() - 1;i >= 0;i --) {
        QLayoutItem* item = container->layout()->takeAt(i);
        if(item != nullptr && item->widget() != nullptr) {
            delete item->widget();
        }
        delete item;
    }
}

void MessageShowArea::verticalBarToEnd()
{
    // since fetching data from the server is asynchronous
    // we need to wait util the data is obtained before scrolling the srcollbar to the end
    QTimer* timer = new QTimer();
    connect(timer, &QTimer::timeout, this, [=](){
        int x = this->verticalScrollBar()->maximum();
        this->verticalScrollBar()->setValue(x);
        timer->stop();
        timer->deleteLater();
    });
    timer->start(500);
}

///////////////////////////////
/// Message Item
///////////////////////////////

MessageItem::MessageItem(bool isLeft)
    :isLeft(isLeft)
{
}

MessageItem *MessageItem::makeMesageItem(bool isLeft, const Message& msg)
{
    MessageItem* msgItem = new MessageItem(isLeft);

    // 1.添加布局管理器
    QGridLayout* layout = new QGridLayout();
    layout->setVerticalSpacing(2);
    layout->setHorizontalSpacing(10);
    layout->setContentsMargins(0, 0, 0, 0);
    msgItem->setLayout(layout);

    // 2.添加头像按钮
    QPushButton* avatarBtn = new QPushButton();
    avatarBtn->setFixedSize(50, 50);
    avatarBtn->setIcon(msg.sender.avatar);
    avatarBtn->setIconSize(QSize(50, 50));
    if(isLeft) {
        layout->addWidget(avatarBtn, 0, 0, 2, 1);
    } else {
        layout->addWidget(avatarBtn, 0, 1, 2, 1);
    }

    // 3.添加名字 + 时间
    QLabel* nameLabel = new QLabel();
    nameLabel->setText(msg.sender.nickname + " | " + msg.time);
    nameLabel->setStyleSheet("QLabel { font-size:15px; }");
    if(isLeft) {
        layout->addWidget(nameLabel, 0, 1, 1, 1);
    } else {
        layout->addWidget(nameLabel, 0, 0, 1, 1, Qt::AlignRight | Qt::AlignBottom);
    }

    // 3.添加正文
    QWidget* contentWidget = nullptr;
    switch(msg.type) {
    case model::TEXT_TYPE:
        contentWidget = makeTextMessage(isLeft, msg.content);
        break;
    case model::IMAGE_TYPE:
        contentWidget = makeImageMessage();
        break;
    case model::FILE_TYPE:
        contentWidget = makeFileMessage();
        break;
    case model::SPEECH_TYPE:
        contentWidget = makeSpeechMessage();
        break;
    default:
        LOG() << "未知的消息类型";
        break;
    }
    if(isLeft) {
        layout->addWidget(contentWidget, 1, 1, 1, 1);
    } else {
        layout->addWidget(contentWidget, 1, 0, 1, 1);
    }

    // 点击用户头像,弹出用户信息对话框
    connect(avatarBtn, &QPushButton::clicked, msgItem, [msg](){
        UserInfoWidget* userInfoWidget = new UserInfoWidget(msg.sender);
        userInfoWidget->exec();
    });

    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    if(!isLeft) {
        connect(dataCenter, &model::DataCenter::modifyNicknameDone, msgItem, [=](){
            nameLabel->setText(dataCenter->getMyself()->nickname + " | " + msg.time);
        });

        connect(dataCenter, &model::DataCenter::modifyAvatarDone, msgItem, [=](){
            avatarBtn->setIcon(dataCenter->getMyself()->avatar);
        });
    }

    return msgItem;
}

QWidget *MessageItem::makeTextMessage(bool isLeft, const QString& text)
{
    MessageContentLabel* msgContentLabel = new MessageContentLabel(text, isLeft);
    return msgContentLabel;
}

QWidget *MessageItem::makeImageMessage()
{
    return nullptr;
}

QWidget *MessageItem::makeFileMessage()
{
    return nullptr;
}

QWidget *MessageItem::makeSpeechMessage()
{
    return nullptr;
}

///////////////////////////////
/// 消息正文部分
///////////////////////////////

MessageContentLabel::MessageContentLabel(const QString &text, bool isLeft)
    :isLeft(isLeft)
{
    QFont font;
    font.setFamily("微软雅黑");
    font.setPixelSize(16);

    label = new QLabel(this);
    label->setText(text);
    label->setFont(font);
    label->setStyleSheet("QLabel { background-color: transparent; color:rgb(1, 1, 1);"
                         "padding: 0px 10px; "
                         "line-height: 1.2; }");
    label->setWordWrap(true);   // 设置自动换行
}

void MessageContentLabel::paintEvent(QPaintEvent *event)
{
    // 1.计算父元素的宽度
    QObject* obj = this->parent();
    if(!obj->isWidgetType()) {
        return;
    }
    QWidget* parent = dynamic_cast<QWidget*>(obj);
    int width = parent->width() * 0.6; // 文字占父元素 60% 为一行

    // 2.计算文字的行数
    QFontMetrics metrics(this->label->font());
    int totalWidth = metrics.horizontalAdvance(this->label->text());
    int rows = totalWidth / (width - 40) + 1; // 40 表示左右留有 20px 的边距
    if (rows == 1) {
        // 如果此时得到的行数就只有一行
        width = totalWidth + 40;
    }

    // 3.根据行数计算高度
    int height = this->label->font().pixelSize() * 1.2 * rows + 20; // 20 表示上下留有 10px 边距

    // 4.绘制圆角矩形和箭头
    QPainter painter(this);
    QPainterPath path;
    painter.setRenderHint(QPainter::Antialiasing); // 设置抗锯齿
    if(isLeft) {
        // 设置线条颜色和填充颜色
        painter.setPen(QPen(QColor(255, 255, 255)));
        painter.setBrush(QColor(255, 255, 255));
        // 绘制圆角矩形
        painter.drawRoundedRect(10, 0, width, height, 10, 10);
        // 绘制箭头
        path.moveTo(10, 10);
        path.lineTo(0, 15);
        path.lineTo(10, 20);
        path.closeSubpath();
        painter.drawPath(path);
        // 将文字放到绘制的图形中
        this->label->setGeometry(10, 0, width, height);
    } else {
        // 设置线条颜色和填充颜色
        painter.setPen(QPen(QColor(137, 217, 97)));
        painter.setBrush(QColor(137, 217, 97));
        // 绘制圆角矩形
        int leftPos = this->width() - 10 - width;
        int rightPos = this->width() - 10;
        painter.drawRoundedRect(leftPos, 0, width, height, 10, 10);
        // 绘制箭头
        path.moveTo(rightPos, 10);
        path.lineTo(rightPos + 10, 15);
        path.lineTo(rightPos, 20);
        path.closeSubpath();
        painter.drawPath(path);
        // 将文字放到绘制的图形中
        this->label->setGeometry(leftPos, 0, width, height);
    }

    // 5. 设置父元素的高度
    parent->setFixedHeight(height + 50);
    this->setMinimumHeight(height); // 让自身高度撑起来
    this->resize(this->width(), height); // 防止被压缩
}





